package com.app.Tree;


import it.unipr.ce.dsg.s2p.sip.Address;

import java.util.ArrayList;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.app.Activity.frmTreeNodeActivity;
import com.app.Controller.NetworkController;
import com.app.Controller.ReadWriteFileController;
import com.app.PhanQuyen.Quyen;

import ReadWriteXML.CMember;
import ReadWriteXML.ReadXML;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.CountDownTimer;
import android.os.Environment;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.EditText;
import android.widget.Toast;

public class BoardViewTN extends SurfaceView implements SurfaceHolder.Callback{
	public static float horizontal = 100;
	public static float vertical = 50;
	public static int T_MOVE = 1;
	public static int T_NEW = 2;
	public static int T_UPDATE = 3;
	private SurfaceHolder holder;
	public BoardLoopThreadText loopThread;
	private TextNode tree;
	TreeMenu tMenu;
	DetailNode detail=new DetailNode();
	public int control = T_MOVE;
	float xDown = -1, yDown = -1, xUp = -1, yUp = -1, x = -1, y = -1;
	private boolean isNew = false;
	private TextNode cNode = null;
	private TextNode newNode = null;
	long downTime = 0, longTime = 0, upTime = 0, tempTime = 0;
	private boolean isTouchUp = false, isTouchDown = false;
	int id = 1;
	int cId = -1;
	public long idnode = 0;
	private long pID;
	public boolean isActive=false;
	private long vs;
	public static String treePath = Environment.getExternalStorageDirectory()+ "/" + "tree.xml";
	public static String DeletedNodesPath=Environment.getExternalStorageDirectory()+"/"+"DeletedNodes.xml";
	public BoardViewTN(Context context) {
		super(context);
		init();
	}
	
	public BoardViewTN(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public BoardViewTN(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	
	private void init() {
		isActive=true;
		getHolder().addCallback(this);
		loopThread = new BoardLoopThreadText(this);

		if(!ReadWriteFileController.isFile(treePath)){
			Log.d("Phu","create Root text node trong BoardviewTN");
			tree=createRoot();
//			Log.d("An", "da tao node goc");
			tree.autoArrangeTextNode();
		}
		else{
			Log.d("Phu","doc textnode tu file trong BoardviewTN");
			readXml(treePath);
			tree.setX(3);
			tree.setY(2);
//			Log.d("An", "doc node goc tu ben kia");
			tree.autoArrangeTextNode();
		}
		this.control = T_MOVE;
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		if(canvas==null)
			return;
		canvas.drawColor(Color.rgb(255, 255, 255));
		tree.onDraw(canvas);
		tree.autoArrangeTextNode();
		//tMenu.onDraw(canvas);
		//detail.onDraw(canvas);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action=event.getAction()&MotionEvent.ACTION_MASK;
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			touchDown(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_MOVE:
			touchMove(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_UP:
//			touchUp(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			
			break;
		default:
			break;
		}
		return true;
	}

	private void touchDown(float x, float y) {
		this.isTouchUp = false;
		this.isTouchDown = true;
		downTime = System.currentTimeMillis();
		control = T_MOVE;
		INode collistionNode=tree.getCollision(x, y);
		if(collistionNode!=null){
			cNode=(TextNode) collistionNode;
			cId=(int) collistionNode.id;			
		}else{
			cNode=null;
			cId=-1;
		}
		if (downTime - tempTime < 400) {
			if (cNode != null && cId != -1)
				control = T_UPDATE;

		}
		final float _x = x, _y = y;
		CountDownTimer count = new CountDownTimer(1000, 10) {
			boolean moved = false;

			@Override
			public void onTick(long millisUntilFinished) {
				if (BoardViewTN.this.x - _x >10 || BoardViewTN.this.y - _y > 10) {
					moved = true;
				}
			}
			@Override
			public void onFinish() {				
				Log.d("Phu", "onFinish trong BoardviewTN: " + moved + isTouchUp + (cNode==null) + cId);
				if (!moved && !isTouchUp) {
					
					if (cNode != null && cId != -1) {
						
						alerDialogWithList();
						Log.d("An", "T_NEW ");
						control = T_NEW;
					}
				}
			}
		}.start();
		this.xDown = x;
		this.yDown = y;
		this.x = x;
		this.y = y;		
	}

	private void touchUp(float x, float y) {
		tempTime = downTime;
		Log.d("An", "detail "+(System.currentTimeMillis()-downTime));
		if(System.currentTimeMillis()-downTime<200){
//			detail=new DetailNode(cNode);	
			//Toast.makeText(getContext(), "detail", 1).show();
		}
		if (control == T_UPDATE) {
//			AlertDialog.Builder alert = new AlertDialog.Builder(this.getContext());
//			final EditText input = new EditText(this.getContext());
//			input.setText(cNode.text);
//			alert.setTitle("Nhập nội dung!");
//			alert.setView(input);
//			alert.setPositiveButton("Cập nhật", new DialogInterface.OnClickListener() {
//				@Override
//				public void onClick(DialogInterface dialog, int which) {
//					cNode.setText(input.getText().toString());
//				}
//			});
//			alert.setNegativeButton("Sắp xếp", new DialogInterface.OnClickListener() {
//
//				@Override
//				public void onClick(DialogInterface dialog, int which) {
////					cNode.autoArrangeTextNode();
//				}
//			});
//			alert.setNeutralButton("Xóa node này", new DialogInterface.OnClickListener() {
//
//				@Override
//				public void onClick(DialogInterface dialog, int which) {
//					Toast.makeText(getContext(), "Xoa node co id=" + cNode.id, 1).show();				
//					tree.remove(cNode);
//					tree.autoArrangeTextNode();	
//				}
//			});
//			alert.show();
			alerDialogWithList();
		} else if (control == T_NEW) {
//			AlertDialog.Builder alert = new AlertDialog.Builder(this.getContext());
//			final EditText input = new EditText(this.getContext());
//			// input.setText("");
//			alert.setTitle("Nhập nội dung!");
//			alert.setView(input);
//			alert.setPositiveButton("Thêm", new DialogInterface.OnClickListener() {
//				@Override
//				public void onClick(DialogInterface dialog, int which) {
//					newNode.setText(input.getText().toString());	
//					//newNode.setY(cNode.y+cNode.heigh+40);
//				}
//			});
//			alert.setNegativeButton("Hủy bỏ", new DialogInterface.OnClickListener() {
//
//				@Override
//				public void onClick(DialogInterface dialog, int which) {					
//					tree.remove(newNode);
//					tree.autoArrangeTextNode();
//				}
//			});
//			alert.show();
			
		}
		cId = -1;
		this.isTouchUp = true;
		this.isTouchDown = false;
		xUp = x;
		yUp = y;
		this.x = x;
		this.y = y;
		control = -1;
		upTime = System.currentTimeMillis();
	}

	private void touchMove(float x, float y) {
		float moveX, moveY, kcX, kcY;
		if (control == T_NEW && newNode != null)
			newNode.setPostion(x, y);
		else if (control == T_MOVE) {
			moveX = x - this.x;
			moveY = y - this.y;
			if (cId != -1 && cNode != null) {
				
				//cNode.setPostion(cNode.x + moveX, cNode.y + moveY);
//				cNode.moveAll(moveX, moveY);
//				if(detail!=null&&detail.node==cNode){
//					detail.moveAll(moveX,moveY);
//				}

			} else {
				tree.moveAll(moveX, moveY);
				if(detail!=null){
					detail.moveAll(moveX,moveY);
				}
			}
			
		}
		this.x = x;
		this.y = y;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// this.setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
	}

//	public boolean addNode(int parentId, TreeNode node) {
//		Log.d("Phu", "Add node in BoardView");
//		{
//			try {
//				if (parentId == -1) {
//					node.setParentNode(null);
//
//				} else {
//					for (TreeNode item : listNode.getData()) {
//
//						if (item.getId() == parentId) {
//							node.setParentNode(item);
//							break;
//						} else
//							node.setParentNode(null);
//					}
//				}
//				node.setBoardView(this);
//				this.listNode.add(node);
//			} catch (Exception e) {
//
//				Log.d("PhuLoi", "Lỗi trong hàm BoardView . addNode" + e.getMessage());
//				return false;
//			}
//			return true;
//		}
//	}

//	public ListNode getNodes() {
//		return this.listNode;
//	}

	public void setTool(int tool) {
		this.control = tool;
	}

//	public void clearNode() {
//		listNode.clear();
//	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		Log.d("Phu", "surfaceCreated BoardViewYN ");

		if (loopThread.getState() == Thread.State.TERMINATED) {
			loopThread = new BoardLoopThreadText(this);
			loopThread.setRunning(true);
			loopThread.start();
		} else {
			loopThread.setRunning(true);
			loopThread.start();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		isActive=false;
		Log.d("Phu", "surfaceDestroyed BoardViewTN");
		boolean retry = true;
		loopThread.setRunning(false);
		while (retry) {
			try {
				loopThread.join();
				retry = false;
			} catch (InterruptedException e) {

			}
		}
	}

	public void removeNode(TextNode node) {
//		if (node == null || node.id == 0) {
//			Log.d("Phu", "return mat roi " + (node == null ? "null" : node.id);
//			return;
//		}
//		int id = (int) node.id;
//		Log.d("Phu", "cid=:" + id);
//		list.add(node);
//		Log.d("Phu", "size=:" + this.listNode.size());
//		for (int i = 0; i < this.listNode.size(); i++) {
//
//			if (this.listNode.get(i).getParentNode() != null) {
//				Log.d("Phu", "node i=" + i + " co id=" + this.listNode.get(i).getId());
//				if (this.listNode.get(i).getParentNode().getId() == id) {
//					Log.d("Phu", "Tien hanh xoa node id=" + this.listNode.get(i).getId());
//					removeNode(this.listNode.get(i));
//				}
//			}
//		}
		tree.remove(node);
	}

	public void sapXepCay(TextNode node) {
//		int id = node.getId();
//		ArrayList<TreeNode> children = new ArrayList<TreeNode>();
//		for (int i = 0; i < listNode.size(); i++) {
//			if (listNode.get(i).getParentNode() != null && listNode.get(i).getParentNode().getId() == id) {
//				children.add(listNode.get(i));
//			}
//		}
//		float firstX = node.getX() + TreeNode.width;
//		// firstX-=horizontal*children.size();
//		firstX -= TreeNode.width * children.size();
//		if (children.size() > 2)
//			firstX /= 2;
//		float firstY = node.getY() + TreeNode.heigh + vertical;
//		for (int i = 0; i < children.size(); i++) {
//			children.get(i).setX(firstX + i * (TreeNode.width) + TreeNode.width / 2);
//			children.get(i).setY(firstY);
//			sapXepCay(children.get(i));
//		}
	}
	public void writeXML(String path){
		tree.writeXML(path);
		Log.d("Phu", "BoardviewTN.writeXML: Da ghi cay xuong file:" + path);
	}
	
	
	//An
	public void alerDialogWithList(){
		final CharSequence[] items = {"Thêm Mới", "Cập Nhật", "Xóa"};

		AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
		builder.setTitle("Thao tác ");
		builder.setItems(items, new DialogInterface.OnClickListener() {
		    public void onClick(DialogInterface dialog, int item) {
		        Log.d("Phu", "gia tri dialog trong BoardviewTN: " + item + items[item]);
		        if(item == 0)
		        	alerDialogCreateNewNode();
		        else if(item == 1)
		        	alerDialogUpdateNode();
		        else if(item == 2)
		        	alerDialogDeleteNode();
		    }
		});
		builder.show();
		//AlertDialog alert = builder.create();
	}

	public void alerDialogCreateNewNode(){
		
			Log.d("Phu", "trong BoardviewTN Id: " + cNode.getId());
			final MyDialog dialog=new MyDialog(getContext(),"Tạo node mới!");
			dialog.show();
			Log.d("Phu", "ok click tao moi trong BoardviewTN:"+dialog.isOkClick());
			dialog.setOKClickListener(new MyHandlerInterface() {
				
				@Override
				public void onHandle(Object obj) {
					Quyen themNode = NetworkController._peer.getAccount()
					.getRuleById(16);
					if (themNode != null && themNode.getSend()) {
						final float _x = x, _y = y;
						vs = System.currentTimeMillis();
						pID=cNode.getId();				
						newNode=new TextNode(NetworkController.getPersonID(),dialog.getTextTitle(),dialog.getText(), _x, _y, NetworkController._peer.getAccount().get_Username(),vs,0,pID);							
						cNode.add(newNode);	
						tree.version= vs;
						TreeNode tn = new TreeNode();
						tn.parse(newNode.toParse());
						frmTreeNodeActivity.idNode=pID;
						frmTreeNodeActivity.nodeAdd=tn;
						Handler hander = new Handler();
						hander.post(frmTreeNodeActivity.raAddnode);						
						tree.autoArrangeTextNode();
						cNode = newNode;						
						
						//Gửi thông tin cho các thành viên
						ArrayList<CMember> members=ReadWriteFileController.readMember(ReadWriteFileController.MEMBER_PATH);
						for(CMember m:members){							
							NetworkController.sendAddTreeNode(new Address(m.get_ip()), pID, newNode);						
					}
					}else{
						Toast.makeText(getContext(),
								"Bạn không có quyền thêm node!",
								Toast.LENGTH_SHORT).show();
					}
				}
			});
			dialog.setCancelClickListener(new MyHandlerInterface() {
				
				@Override
				public void onHandle(Object obj) {
					dialog.cancel();
				}
			});
	}
	
	public void alerDialogUpdateNode(){
		boolean update = true;
		Quyen q = NetworkController._peer.getAccount()
		.getRuleById(17);
		String loi = "";
			if (q == null || (q != null && q.getSend() == false)) {
				update = false;
				loi = "Bạn không có quyền sửa!";
				
			}else{
				// Tìm xem node có node con của người khác ko
				if (cNode.getUser() == NetworkController._peer
						.getAccount().get_Username()) {
					boolean haveChildren = cNode
							.haveOtherChildren(NetworkController._peer
									.getAccount()
									.get_Username());
					if (haveChildren) {
						update = false;
						loi = "Không thể sửa khi có ý kiến của người khác!";
					} else {
						update = true;
					}
				} else {
					update = false;
					loi = "Không thể sửa ý kiến của người khác!";
				}
			}
			if (update) {
				final MyDialog dialog=new MyDialog(getContext(),"Cập nhật node!",cNode.getTitle(),cNode.getText());
				dialog.show();
				Log.d("Phu", "ok click Upadate:"+dialog.isOkClick());
				dialog.setOKClickListener(new MyHandlerInterface() {
					
					@Override
					public void onHandle(Object obj) {
						cNode.setText(dialog.getText().toString());
						cNode.setTitle(dialog.getTextTitle());
						cNode.setLabel(1);
						cNode.setVersion(System.currentTimeMillis());
						TreeNode t = new TreeNode();
						t.parse(cNode.toParse());
						frmTreeNodeActivity.nodeAdd = t;
						Handler hander = new Handler();
						hander.post(frmTreeNodeActivity.raUpdateNode);
						ArrayList<CMember> members=ReadWriteFileController.readMember(ReadWriteFileController.MEMBER_PATH);
						for(CMember m:members){
							Log.d("Phu", "pID update trong BoardviewTN" + pID +" - "+ m.get_ip());
							NetworkController.sendUpdateNodeText(new Address(m.get_ip()), cNode);							
						}
					}
				});
				dialog.setCancelClickListener(new MyHandlerInterface() {
					
					@Override
					public void onHandle(Object obj) {
						dialog.cancel();
					}
				});
			} else {
				Toast.makeText(getContext(), loi,
						Toast.LENGTH_SHORT).show();
			}
	}
	
	public void alerDialogDeleteNode(){

		boolean delete = true;
		Quyen q = NetworkController._peer.getAccount()
				.getRuleById(17);
		String loi = "";

		// Kiểm tra có quyền xóa node ko?
		if (q == null || (q != null && q.getSend() == false)) {
			delete = false;
			loi = "Bạn không có quyền xóa!";			
		}else{
			// Tìm xem node có node con của người khác ko
			if (cNode.getUser() == NetworkController._peer
					.getAccount().get_Username()) {
				boolean haveChildren = cNode
						.haveOtherChildren(NetworkController._peer
								.getAccount()
								.get_Username());
				if (haveChildren) {
					delete = false;
					loi = "Không thể xóa khi có ý kiến của người khác!";
				} else {
					delete = true;
				}
			} else {
				delete = false;
				loi = "Không thể xóa ý kiến của người khác!";
			}
		}

		if (delete) {
			Toast.makeText(getContext(),"Xoa node co id=" + cNode.id, 1).show();
			vs = System.currentTimeMillis();
			tree.remove(cNode);
			cNode.version = vs;
			tree.version = vs;
			TreeNode t = new TreeNode();
			t.parse(cNode.toParse());
			frmTreeNodeActivity.nodeAdd = t;
			Handler hander = new Handler();
			hander.post(frmTreeNodeActivity.raDeleteNode);
			// Gửi thông tin cho các thành viên
			ArrayList<CMember> members = ReadWriteFileController
					.readMember(ReadWriteFileController.MEMBER_PATH);
			for (CMember m : members) {
				NetworkController.sendDeleteTreeNode(new Address(m.get_ip()),cNode);
			}
		} else {
			Toast.makeText(getContext(), loi,
					Toast.LENGTH_SHORT).show();
		}
	}
	
	public void addNode(long idParent, INode node){
		INode p=tree.getById(idParent);
		if(p!=null)
			tree.version = node.getVersion();
			p.add(node);
	}
	public void addTextNode(long idParent, INode node, String path){
		if (!isActive) {
			Log.d("123"," board view TN ko active - ghi xuong file: ");
			this.readXml(path);
			INode p = tree.getById(idParent);
			if (p != null){
				p.add(node);
				tree.version = node.getVersion();
				writeXML(path);
			}
		} else {			
			addNode(idParent, node);
			tree.autoArrangeTextNode();			
		}
	}
	
	public void readXml(String path) {
		Document doc = ReadXML.BuildXML(path);
		tree = new TextNode();
		tree.readXML((Element) doc.getFirstChild().getFirstChild());
		Log.d("Phu","Đã đọc cây từ file lên trong BoardviewTN: số node con= "+tree.getChildren().size());
	}
	
	public static TextNode createRoot(){
		Log.d("An", "Tao node goc");
		TextNode rs=new TextNode(1, "[]", "", 2, 3, "[Hệ thống]", System.currentTimeMillis(),0,0);
		rs.writeXML(treePath);
		return rs;
	}
	//end

	public TextNode getTree() {
		return tree;
	}

	public void updateText(INode node, String path) {
		if (!isActive) {
			Log.d("123", "BoardviewTn ko active..");
			this.readXml(path);
			INode inode = tree.getById(node.getId());
			if (inode != null) {
				inode.copy(node);
				tree.version = node.getVersion();
				writeXML(path);
			}			
		} else {
			INode inode = tree.getById(node.getId());
			if (inode != null) {
				tree.version = node.getVersion();
				inode.copy(node);
				Log.d("123", "BoardviewTn active. add vào cây lun.");
			}
		}
	}
	
	public void removeNodeById(INode node, String path, String delpath) {
		tree.version = node.getVersion();
		if(isActive){
			removeNodeByID(node.getId());
		}else{
			this.readXml(path);
			this.removeNodeByID(node.getId());
			Log.d("123", "BoardviewTn - da xoa node.. vs delnode"+ node.getVersion());
			tree.version = node.getVersion();
			Log.d("123", "BoardviewTn - da xoa node.. vs tree"+ tree.getVersion());
			writeXML(path);
			writeDeleteXML(delpath,node.id,node.version);
		}		
		tree.autoArrangeTextNode();
	}
	
	public void writeDeleteXML(String path, long id, long vs){
		tree.writeDeletedXML(path, id, vs);
		Log.d("Phu","Boardview.writeXML: Da ghi cay xuong file:"+path);
	}
	
	public void removeNodeByID(long id) {
		INode n = tree.getById(id);
		tree.remove(n);
		Log.d("An", "BoardviewTn - da xoa node.." + id);
	}
	
	public void autoArrange() {
		tree.autoArrangeTextNode();
		
	}
	
	public void settree(float x, float y){
		tree.setX(x);
		tree.setY(y);
	}
	
}
